<template>
  <div class="base-custom-switch" :class="globalSize" :title="title">
    <input v-model="check" type="checkbox" class="checkbox" :tabindex="tabindex" />
    <div class="knobs" :class="check ? 'active' : 'inactive'">
      <span class="icon">
        <span style="display: block; transform: scale(0.85)">
          <component :is="check ? activeIcon : inactiveIcon"></component>
        </span>
        {{ check ? activeText : inactiveText }}
      </span>
    </div>
  </div>
</template>

<script setup lang="ts">
  import { type Component, type PropType, computed, ref, watch } from 'vue';

  const props = defineProps({
    /** 标题(原生属性) */
    title: { type: String, default: '0' },
    /** tab键切换的顺序下标 */
    tabindex: { type: String, default: '0' },
    /** 当前状态的值 */
    modelValue: { type: [Boolean, String, Number], default: false },
    /** 选中状态的值 */
    activeValue: { type: [Boolean, String, Number], default: true },
    /** 未选中状态的值 */
    inactiveValue: { type: [Boolean, String, Number], default: false },
    /** 选中状态下展示的文字 */
    activeText: { type: String, default: '' },
    /** 选未状态下展示的文字 */
    inactiveText: { type: String, default: '' },
    /** 选中状态下展示的图标 */
    activeIcon: { type: [String, Object] as PropType<Component | string>, default: undefined },
    /** 未选中状态下展示的图标 */
    inactiveIcon: { type: [String, Object] as PropType<Component | string>, default: undefined },
    /** 组件的大小 */
    size: { type: String as PropType<$GlobalSize | ''>, default: '' }, // 大小 default / large / small
  });

  const emit = defineEmits<{
    (e: 'update:modelValue', value: boolean | number | string): void;
  }>();

  const globalSize = computed(() => props.size || useGlobalStore().globalSize);

  const check = ref(Boolean(props.modelValue === props.activeValue));

  watch(
    () => props.modelValue,
    (val) => {
      check.value = Boolean(val === props.activeValue);
    }
  );

  watch(
    () => check.value,
    (state) => {
      emit('update:modelValue', state ? props.activeValue : props.inactiveValue);
    }
  );
</script>

<style scoped lang="scss">
  .base-custom-switch {
    --my-switch-active-bg-color: var(--el-bg-color);
    --my-switch-inactive-bg-color: var(--el-bg-color);
    --my-switch-bg-color: var(--el-fill-color);
    --my-switch-border-color: var(--el-border-color-lighter);
    --my-switch-hover-border-color: var(--el-border-color);

    @include flex(row, nowrap, flex-start, center, center);
    position: relative;
    width: var(--my-switch-width);
    height: var(--my-switch-height);
    padding: 2px;
    overflow: hidden;
    background: var(--my-switch-bg-color);
    border-radius: 20px;
    box-shadow: 0 0 0 1px var(--my-switch-border-color) inset;
    transition: 0.2s ease all;

    &:hover {
      box-shadow: 0 0 0 1px var(--my-switch-hover-border-color) inset;
    }

    &:focus-within {
      box-shadow: 0 0 0 1px var(--el-color-primary) inset;
    }

    &.large {
      --my-switch-width: 56px;
      --my-switch-height: 28px;
    }

    &.default {
      --my-switch-width: 48px;
      --my-switch-height: 24px;
    }

    &.small {
      --my-switch-width: 40px;
      --my-switch-height: 20px;
    }

    .checkbox {
      position: absolute;
      top: 0;
      left: 0;
      z-index: 2;
      width: 100%;
      height: 100%;
      cursor: pointer;
      opacity: 0;
    }

    .knobs {
      --icon-box-size: calc(var(--my-change-base12-2x-size) + 4px);

      @include flex(row, nowrap, center, center, center);
      width: var(--icon-box-size);
      height: var(--icon-box-size);
      font-size: var(--my-change-base12-2x-size);
      border-radius: 50%;
      transition: 0.2s ease all;

      &.active {
        background: var(--my-switch-active-bg-color);
        transform: translateX(0);
      }

      &.inactive {
        background: var(--my-switch-inactive-bg-color);
        transform: translateX(calc(var(--my-switch-width) - var(--icon-box-size) - 6px)); // padding+border为6
      }

      .icon {
        font-size: var(--my-change-base12-2x-size);
        line-height: 1em;
        transform: scale(0.9);
      }
    }
  }
</style>
